﻿using System.Collections.Generic;
using Microsoft.Xna.Framework;
using SaveTheQueen.Component;
using SaveTheQueen.Utils.Colision;

namespace SaveTheQueen.Utils
{
    public delegate void ColisionHandler(Sprite a, Sprite b);
    public enum DefautColisionReactions
    {
        ChangeTint, NegateSpeed, Destroy, PerfectElastic, PerfectPlastic
    }

    public class ColisionManager
    {
        public event ColisionHandler OnColision;
        private BaseAccelerator accel;
        private BaseShape shape;
        private List<Sprite> nodes;
        private List<Sprite> pairsThatCollided;
        private List<ContainmentType> colisionType;
        private bool isRunning;

        /// <summary>
        /// Objects that are going to be checked for colision with each other.
        /// </summary>
        public List<Sprite> Nodes
        {
            get { return nodes; }
        }

        public ColisionManager()
        {
            nodes = new List<Sprite>();
            pairsThatCollided = new List<Sprite>();
            accel = new PermutationAccel();
            shape = new InnerCircleShape();
        }

        public void StartChecking()
        {
            pairsThatCollided.Clear();
            isRunning = true;

            accel.Start();
            while (isRunning)
            {
                accel.NextPair(this);
            }
            for (int i = 0; i < pairsThatCollided.Count; i += 2)
            {   // call the handler for each pair that collided..
                OnColision(pairsThatCollided[i], pairsThatCollided[i + 1]);
            }
            accel.End();
        }

        public void ClearEvents()
        {
            OnColision = null;
        }
        public void DefautEvents(DefautColisionReactions reaction)
        {
            switch (reaction)
            {
                case DefautColisionReactions.ChangeTint:
                    OnColision += delegate(Sprite a, Sprite b)
                    {   // Both turn violet. (Manual clean up is required (set Tint to White when there is no colision.)
                        a.Tint = Color.Violet;
                        b.Tint = Color.Violet;
                    };
                    break;
                case DefautColisionReactions.NegateSpeed:
                    OnColision += delegate(Sprite a, Sprite b)
                    {   // Both have their speed negated.
                        a.Speed *= -1;
                        b.Speed *= -1;
                    };
                    break;
                case DefautColisionReactions.Destroy:
                    OnColision += delegate(Sprite a, Sprite b)
                    {   // Both objects are removed.
                        a.DestroySelf();
                        b.DestroySelf();
                    };
                    break;
                case DefautColisionReactions.PerfectElastic:
                    OnColision += delegate(Sprite a, Sprite b)
                    {   // They change speeds, not the same as negate, 'cause here they exange their speed value, not only the way they are going.
                        Vector2 aux = a.Speed;
                        a.Speed = b.Speed;
                        b.Speed = aux;
                    };
                    break;
                case DefautColisionReactions.PerfectPlastic:
                    OnColision += delegate(Sprite a, Sprite b)
                    {   // All speed is lost
                        a.Speed = Vector2.Zero;
                        b.Speed = Vector2.Zero;
                    };
                    break;
            }
        }

        internal void CheckPair(Sprite a, Sprite b)
        {
            if (a == null | b == null)
            {
                isRunning = false; // finishes the checks.
            }
            else
            {
                if (shape.Intersect(a, b))
                {   // there was a colision
                    pairsThatCollided.Add(a);
                    pairsThatCollided.Add(b);
                }   // else, there was no colision.
            }
        }
    }
}
